﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microhard.WarehouseInsp.Buz.Interfaces;
using Microhard.WarehouseInsp.Buz.DataAccess;
using Microhard.Core.DBUtility;
using Microhard.Core;
using Microhard.WarehouseInsp.Buz.Msg;
using Microhard.WarehouseInsp.Buz.Models;
using Microhard.WarehouseInsp.Buz.DTO;
using Microhard.WarehouseInsp.Buz.BuzEnum;
namespace Microhard.WarehouseInsp.Buz.Impls
{
    public class OutIntPutWarehouseImpl : IOutIntPutWarehouse
    {

        /// <summary>
        /// 得到仓库里所有正在执行的项目
        /// </summary>
        /// <returns></returns>
        public List<SupProjectModel> GetProjectByWarehouse()
        {

            WarehouseInspEntities entities = new WarehouseInspEntities();
            var v = from p in entities.PledgePlanInRecords
                    where p.Warehouse.WarehouseMngID == scope.CurrentUserID &&
                    p.SupProject.Status == (int)PrjStatus.Finished
                    select p.SupProject;
            var list = v.ToList();

            return list.Select(e => e.ToModel()).ToList();
        }

        /// <summary>
        /// 添加入库
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public ExecutedResult Add(Models.OutIntPutWarehouseModel model)
        {
            ExecutedResult rtn = new ExecutedResult();
            WarehouseInspEntities db = new WarehouseInspEntities();

            #region 出入库记录 modified by chenglin 0916
            var op = model.ToEntity();
            op.CreateTime = DateTime.Now;
            op.PlayExTime = DateTime.Now;

            //如果是出库申请，则从列表中传入选择的质押物
            //added by chenglin 20140902
            if (model.OutInPutType == (int)OutInPutType.Out)
            {
                op.PlnPdgID = Guid.Parse(model.InProductIDForSelect);
                op.Status = (int)PrjStatus.Saved;
            }
            else //如果是入库，则直接添加。
            {
                op.PlnPdgID = model.PlnPdgID;
                op.OutInPutApplyID = Guid.Empty;
                op.Status = (int)PrjStatus.InWarehouseFinished;
            }
            //出入库的时候可以填写单价，也可以填写总价
            //如果有总价，则用总价金额除以数量，获得单价
            if (model.OutInAmount > 0)
            {
                op.OutInPrice = model.OutInAmount / (decimal)model.OutInCount;
                op.OutInAmount = model.OutInAmount;
            }
            else
            {
                op.OutInAmount = (decimal)(model.OutInCount) * model.OutInPrice;
            }
            db.OutInPutWarehouseRecords.AddObject(op);
            #endregion

            #region 入库货值变动记录 modified by chenglin 0916
            PledgeChangeRecord pcrm = new PledgeChangeRecord();
            var oldmodel = (from p in db.PledgeChangeRecords
                            where p.PlnPdgID == model.PlnPdgID
                            && p.IsUsing == true
                            orderby p.CreateTime descending
                            select p).FirstOrDefault();
            if (model.OutInPutType == (int)OutInPutType.In) //入库
            {
                if (oldmodel != null)
                {
                    pcrm.CurrentCount = oldmodel.CurrentCount + op.OutInCount;
                    pcrm.CurrentPrice = op.OutInPrice;
                    pcrm.CurrentAmount = oldmodel.CurrentAmount + op.OutInAmount;
                    oldmodel.IsUsing = false;
                }
                else
                {
                    pcrm.CurrentCount = op.OutInCount;
                    pcrm.CurrentPrice = op.OutInPrice;
                    pcrm.CurrentAmount = op.OutInAmount;
                }

                pcrm.CreateTime = DateTime.Now;
                pcrm.CurrentPrice = model.OutInPrice;
                pcrm.IsUsing = true;
                pcrm.PlnPdgID = model.PlnPdgID;
                pcrm.PledgeProductID = Guid.NewGuid();
                pcrm.OutInPutWarehouseRecordsID = op.OutInPutWarehouseID;
                pcrm.UpdateTime = DateTime.Now;
                pcrm.OperatorID = this.scope.CurrentUserID;
                pcrm.OperatorName = this.scope.CurrentUserRealName;
                pcrm.RecordType = (int)RecordType.OutInPut;
                db.PledgeChangeRecords.AddObject(pcrm);
            }
            #endregion

            try
            {
                db.SaveChanges();
            }
            catch (System.Exception ex)
            {
                rtn.ErrorMsg.Add(DBOperationFailedStatus.AddFailed, ProductListMsg.AddFailed);
                Log.Error("IOutIntPutWarehouse.Add", ex);
            }

            return rtn;
        }


        public ExecutedResult Update(Models.OutIntPutWarehouseModel model)
        {
            ExecutedResult result = new ExecutedResult();
            WarehouseInspEntities db = new WarehouseInspEntities();
            var entity = db.OutInPutWarehouseRecords.SingleOrDefault(l => l.OutInPutWarehouseID == model.OutInPutWarehouseID);
            //如果是监管员，且数据是入库完毕或出库完毕状态，则不能修改数据
            if (this.scope.CurrentUserRoleNames.Contains(SysConst.SUPOTALROLENAME))
            {
                if (entity.Status == (int)PrjStatus.InWarehouseFinished || entity.Status == (int)PrjStatus.OutWarehouseFinished)
                {
                    result.ErrorMsg.Add(DBOperationFailedStatus.UpdateFailed, "数据确认完毕，不能修改");
                    return result;
                }
            }
            var oldmodel = db.PledgeChangeRecords.SingleOrDefault(w => w.PlnPdgID == entity.PlnPdgID && w.IsUsing == true);
            if (entity != null)
            {
                PledgeChangeRecordModel pmodel = new PledgeChangeRecordModel();
                bool canUpdateChangeRecords = false;
                entity.OutInCount = model.OutInCount;
                entity.OutInPrice = model.OutInPrice;

                //入库的时候可以填写单价，也可以填写总价
                //如果有总价，则用总价金额除以数量，获得单价
                if (model.OutInAmount > 0)
                {
                    entity.OutInPrice = model.OutInAmount / (decimal)model.OutInCount;
                    entity.OutInAmount = model.OutInAmount;
                }
                else
                {
                    entity.OutInAmount = (decimal)(model.OutInCount) * model.OutInPrice;
                }

                if (model.OutInPutType == (int)OutInPutType.In) //入库
                {
                    //如果是数据专员，则可以修改已经出库的数据
                    entity.PlayExTime = model.PlayExTime;
                    if (oldmodel != null)
                    {
                        pmodel.CurrentCount = oldmodel.CurrentCount + entity.OutInCount;
                        pmodel.CurrentAmount = oldmodel.CurrentAmount + entity.OutInAmount;
                        canUpdateChangeRecords = true;
                        oldmodel.IsUsing = false;
                    }
                }
                else if (model.OutInPutType == (int)OutInPutType.Out)//出库
                {
                    if (entity.Status == (int)PrjStatus.Finished)
                    {
                        entity.Status = (int)PrjStatus.OutWarehouseFinished;
                        if (oldmodel != null)
                        {
                            pmodel.CurrentCount = oldmodel.CurrentCount - entity.OutInCount;
                            pmodel.CurrentAmount = oldmodel.CurrentAmount - entity.OutInAmount;
                            canUpdateChangeRecords = true;
                            oldmodel.IsUsing = false;
                        }
                    }
                }

                if (canUpdateChangeRecords)
                {
                    pmodel.CreateTime = DateTime.Now;
                    pmodel.CurrentPrice = model.OutInPrice;
                    pmodel.IsUsing = true;
                    pmodel.PlnPdgID = model.PlnPdgID;
                    pmodel.PledgeProductID = Guid.NewGuid();
                    pmodel.UpdateTime = DateTime.Now;
                    pmodel.OperatorID = this.scope.CurrentUserID;
                    pmodel.OperatorName = this.scope.CurrentUserRealName;
                    pmodel.RecordType = (int)RecordType.OutInPut;
                    pmodel.OutInPutWarehouseRecordsID = entity.OutInPutWarehouseID;
                    var pE = pmodel.ToEntity();
                    db.PledgeChangeRecords.AddObject(pE);
                }
                try
                {
                    db.SaveChanges();
                }
                catch (Exception ex)
                {
                    result.ErrorMsg.Add(DBOperationFailedStatus.UpdateFailed, PledgePlanInRecordsMsg.UpdateFailed);
                    Log.Error("IOutIntPutWarehouse.Update", ex);
                }

            }
            return result;
        }

        public ExecutedResult Delete(List<Guid> ids)
        {
            ExecutedResult result = new ExecutedResult();
            WarehouseInspEntities entity = new WarehouseInspEntities();
            try
            {
                if (ids != null && ids.Count > 0)
                {
                    //需要删除货值变动数据
                    //modified by chenglin 0916
                    var v = entity.OutInPutWarehouseRecords.Where(e => ids.Contains(e.OutInPutWarehouseID)).ToList();
                    v.ForEach(i =>
                    {
                        //删除货值变动记录
                        var change = entity.PledgeChangeRecords.SingleOrDefault(w => w.OutInPutWarehouseRecordsID == i.OutInPutWarehouseID);
                        if (change == null)
                        {
                            Log.Error(DBOperationFailedStatus.DeleteFailed, "无法获取货值变动记录,OutInPutWarehouseRecordsID:" + i.OutInPutWarehouseID);
                        }
                        else
                        {
                            //重置最近的一次货值记录为最新的
                            var latestchange = entity.PledgeChangeRecords.Where(p => p.PlnPdgID == change.PlnPdgID && p.IsUsing == false)
                                .OrderByDescending(s => s.CreateTime).First();
                            latestchange.IsUsing = true;

                            entity.PledgeChangeRecords.DeleteObject(change);
                        }
                        //删除出入库记录
                        entity.OutInPutWarehouseRecords.DeleteObject(i);
                    });

                    entity.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                result.ErrorMsg.Add(DBOperationFailedStatus.DeleteFailed, PledgePlanInRecordsMsg.DeleteFailed);
                Log.Error("IOutIntPutWarehouse.Delete", ex);
            }

            return result;

        }

        public ExecutedResult Delete(Models.OutIntPutWarehouseModel model)
        {
            throw new NotImplementedException();
        }


        /// <summary>
        /// 得到出入库记录
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Models.OutIntPutWarehouseModel GetModelByID(Guid id)
        {
            WarehouseInspEntities entity = new WarehouseInspEntities();
            var v = entity.OutInPutWarehouseRecords.SingleOrDefault(e => e.OutInPutWarehouseID == id);
            if (v != null)
            {
                OutIntPutWarehouseModel model = v.ToModel();
                var vv = from p in entity.ProductLists where p.ProductID == model.PPInRecord.ProductID select p.Name;
                model.ProductName = vv.SingleOrDefault();
                return model;
            }
            return null;
        }

        public Models.OutIntPutWarehouseModel GetModelByModel(Models.OutIntPutWarehouseModel model)
        {
            throw new NotImplementedException();
        }



        /// <summary>
        /// 得到入库列表
        /// </summary>
        /// <param name="Model"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="totalCount"></param>
        /// <returns></returns>

        public List<Models.OutIntPutWarehouseModel> Query(Models.OutIntPutWarehouseModel Model, int pageIndex, int pageSize, out int totalCount)
        {
            WarehouseInspEntities entity = new WarehouseInspEntities();
            IEnumerable<OutInPutWarehouseRecord> entities = from p in entity.OutInPutWarehouseRecords
                                                            where (p.PledgePlanInRecord.Warehouse.WarehouseMngID == this.scope.CurrentUserID
                                                            || p.PledgePlanInRecord.SupProject.PMID == this.scope.CurrentUserID
                                                            || p.PledgePlanInRecord.SupProject.CreatorID == this.scope.CurrentUserID)
                                                            && p.OutInPutType == Model.OutInPutType
                                                            select p;
            if (Model.OutInPutApplyID != Guid.Empty)
            {
                entities = from e in entities
                           where e.OutInPutApplyID == Model.OutInPutApplyID
                           select e;
            }
            if (Model.ProjectID != Guid.Empty)
            {
                entities = from e in entities
                           where e.PledgePlanInRecord.SupProject.ProjectID == Model.ProjectID
                           select e;
            }
            if (Model.Status > 0)
            {
                if (Model.Status == (int)PrjStatus.WithFS)
                {
                    entities = from e in entities
                               where e.Status == (int)PrjStatus.Finished || e.Status == (int)PrjStatus.OutWarehouseFinished
                               select e;
                }
                else
                {
                    entities = from e in entities
                               where e.Status == Model.Status
                               select e;
                }

            }
            totalCount = entities.Count();
            var en = entities.OrderByDescending(d => d.CreateTime).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
            if (en != null && en.Count > 0)
            {
                return en.Select(m => m.ToModel()).ToList();
            }
            return new List<Models.OutIntPutWarehouseModel>();

        }

        public List<Models.OutIntPutWarehouseModel> Query(Models.OutIntPutWarehouseModel Model)
        {
            WarehouseInspEntities entity = new WarehouseInspEntities();
            IEnumerable<OutInPutWarehouseRecord> entities = from p in entity.OutInPutWarehouseRecords
                                                            where (p.PledgePlanInRecord.Warehouse.WarehouseMngID == this.scope.CurrentUserID
                                                            || p.PledgePlanInRecord.SupProject.PMID == this.scope.CurrentUserID
                                                            || p.PledgePlanInRecord.SupProject.CreatorID == this.scope.CurrentUserID)
                                                            && p.OutInPutType == Model.OutInPutType
                                                            select p;
            if (Model.OutInPutApplyID != Guid.Empty)
            {
                entities = from e in entities
                           where e.OutInPutApplyID == Model.OutInPutApplyID
                           select e;
            }
            if (Model.ProjectID != Guid.Empty)
            {
                entities = from e in entities
                           where e.PledgePlanInRecord.SupProject.ProjectID == Model.ProjectID
                           select e;
            }
            if (entities != null && entities.Count() > 0)
            {
                return entities.Select(m => m.ToModel()).ToList();
            }
            return new List<Models.OutIntPutWarehouseModel>();
        }

        public ScopeResult scope
        {
            get;
            set;
        }

        /// <summary>
        /// 得到申请出库的产品列表
        /// </summary>
        /// <param name="OutPutApplyID"></param>
        /// <returns></returns>
        public List<OutIntPutWarehouseModel> GetOutRecordByApplyID(Guid OutPutApplyID)
        {
            WarehouseInspEntities entity = new WarehouseInspEntities();
            var v = entity.OutInPutWarehouseRecords.Where(e => e.OutInPutApplyID == OutPutApplyID).ToList();
            if (v != null && v.Count > 0)
                return v.Select(m => m.ToModel()).ToList();
            return new List<OutIntPutWarehouseModel>();
        }

        /// <summary>
        /// 根据项目得到已入库产品列表
        /// </summary>
        /// <param name="ProjectID"></param>
        /// <returns></returns>
        public List<OutIntPutWarehouseModel> GetInRecordByProject(Guid ProjectID)
        {
            WarehouseInspEntities entity = new WarehouseInspEntities();
            var v = from o in entity.OutInPutWarehouseRecords
                    where o.PledgePlanInRecord.ProjectID == ProjectID
                    && o.OutInPutType == 1
                    select o;
            if (v != null && v.Count() > 0)
                return v.ToList().Select(m => m.ToModel()).ToList();
            return new List<OutIntPutWarehouseModel>();
        }

        public List<OutIntPutWarehouseModel> GetOutRecordByProject(Guid ProjectID)
        {
            WarehouseInspEntities entity = new WarehouseInspEntities();
            var v = from o in entity.OutInPutWarehouseRecords
                    where o.PledgePlanInRecord.ProjectID == ProjectID
                    && o.OutInPutType == 2
                    select o;
            if (v != null && v.Count() > 0)
                return v.ToList().Select(m => m.ToModel()).ToList();
            return new List<OutIntPutWarehouseModel>();
        }


        public bool IsOutCount(Guid plgID, double outNewAmount)
        {
            bool rtn = true;
            WarehouseInspEntities entity = new WarehouseInspEntities();
            //质押物出库的时候，因为有多条入库记录，所以使用where
            var cnt = entity.OutInPutWarehouseRecords.Where(s => s.PlnPdgID == plgID
                && s.OutInPutType.Value == (int)OutInPutType.In);
            if (cnt != null)
            {
                if (outNewAmount <= (double)cnt.Sum(x => x.OutInAmount))
                    rtn = false;
            }
            return rtn;
        }



        public OutIntPutWarehouseModel GetByOutInPutWarehouseID(Guid OutInPutWarehouseID)
        {
            WarehouseInspEntities entity = new WarehouseInspEntities();
            var cnt = entity.OutInPutWarehouseRecords.SingleOrDefault(s => s.OutInPutWarehouseID == OutInPutWarehouseID);
            if (cnt != null)
                return cnt.ToModel();
            return null;
        }


        public bool HasAddPlg(Guid plgID, Guid applyID)
        {
            WarehouseInspEntities entity = new WarehouseInspEntities();
            var cnt = entity.OutInPutWarehouseRecords.Count(s => s.PlnPdgID == plgID && s.OutInPutApplyID == applyID);
            return cnt > 0 ? true : false;
        }
    }
}
